/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.repair.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springblade.common.cache.DictCache;
import org.springblade.common.filter.LogFilter;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.log.annotation.ApiLog;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tenant.annotation.TenantIgnore;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.repair.dto.MaintainPlanCalendarDataDTO;
import org.springblade.modules.repair.dto.MaintainPlanCalendarDataDownDTO;
import org.springblade.modules.repair.dto.PlanContentSearchDTO;
import org.springblade.modules.repair.dto.plan.PlanOrderHomePage4SearchDTO;
import org.springblade.modules.repair.dto.plan.PlanOrderHomePageSearchDTO;
import org.springblade.modules.repair.dto.plan.offline.ByPlanOfflineDetailDTO;
import org.springblade.modules.repair.dto.plan.offline.ByPlanOfflineDetailDTO;
import org.springblade.modules.repair.dto.plan.PlanOrderHomePageSearchDTO;
import org.springblade.modules.repair.entity.MaintainPlanContent;
import org.springblade.modules.repair.entity.MaintainPlanContentOffline;
import org.springblade.modules.repair.entity.MaintainSignture;
import org.springblade.modules.repair.enums.*;
import org.springblade.modules.repair.service.*;
import org.springblade.modules.repair.vo.*;
import org.springblade.modules.repair.vo.plan.*;
import org.springblade.modules.repair.vo.plan.OfflineByPlanListVO;
import org.springblade.modules.repair.vo.plan.PlanContentElevatorVo;
import org.springblade.modules.repair.vo.plan.PlanOrderHomePageVO;
import org.springblade.modules.repair.vo.plan.v2.MaintainPlanContentHomeListVo;
import org.springblade.modules.system.entity.Dict;
import org.springblade.modules.system.service.IUserService;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 维保任务表 控制器
 *
 * @author ysq
 * @since 2022-03-28
 */
@RestController
@AllArgsConstructor
@RequestMapping("repair/maintain/plan/content")
@Api(value = "维保任务表", tags = "维保任务表接口")
public class MaintainPlanContentController extends BladeController {

	private final IMaintainPlanContentService planContentService;

	private final MaintainSigntureService signtureService;

	private final IMaintainMalfunctionWorkService malfunctionWorkService;

	private final IUserService userService;

	private final MaintainTemplateService templateService;

	private final MaintainPlanContentOfflineService planContentOfflineService;

	/**
	 * 获取当前时间
	 * @return
	 */
	@GetMapping("/service/time")
	public R<?> selectServiceTime(){
		return R.data(new Date());
	}

	/**
	 * 获取任务状态及关联人员列表
	 * @param planId
	 * @return
	 */
	@TenantIgnore
	@GetMapping("/detail")
	public R<?> planDetail(Long planId){
		return R.data(planContentService.selectPlanDetail(planId));
	}

	/**
	 * 获取保养工单及上次保养工单时间
	 * @param planId
	 * @return
	 */
	@TenantIgnore
	@GetMapping("/simple/detail")
	public R<Map<String,Object>> planSimpleDetail(Long planId){
		return R.data(planContentService.selectPlanSimpleDetail(planId));
	}

	/**
	 * 获取任务模板下模板分类所有根节点 模板预览
	 * @param templateId
	 * @return
	 */
	@TenantIgnore
	@GetMapping("/location/type/preview")
	public R<List<PlanDetailLocationTypeVO>> locationTypePreview(Long templateId){
		return R.data(planContentService.getPlanLocationTypePreview(templateId));
	}

	/**
	 * 获取任务工作项 模板预览
	 * @param templateId
	 * @param tltId
	 * @return
	 */
	@TenantIgnore
	@GetMapping("/work/item/preview")
	public R<List<PlanTemplateVO>> workItemPreview(Long templateId, Long tltId){
		return R.data(planContentService.workItemPreview(templateId,tltId));
	}

	/**
	 * 获取任务模板下模板分类所有根节点
	 * @param planId
	 * @return
	 */
	@TenantIgnore
	@GetMapping("/location/type")
	public R<Map<String, Object>> locationType(Long planId){
		return R.data(planContentService.getPlanLocationType(planId));
	}

	/**
	 * 获取任务工作项
	 * @param planId
	 * @param tltId
	 * @return
	 */
	@TenantIgnore
	@GetMapping("/work/item")
	public R<List<PlanTemplateVO>> workItem(Long planId, Long tltId,Long templateId){
		return R.data(planContentService.getPlanWorkItem(planId,tltId,templateId));
	}

	/**
	 * 获取任务工作项列表
	 * @param planId
	 * @return
	 */
	@LogFilter
	@TenantIgnore
	@GetMapping("/work/item/list")
	public R<List<PlanTemplateContentVO>> workItemList(Long planId){
		return R.data(planContentService.getPlanWorkItemList(planId));
	}

	/**
	 * 任务提交
	 * @param planContent
	 * @return
	 */
	@ApiLog("保养-工单提交")
	@PostMapping("/commit")
	public R<Boolean> planCommit(@RequestBody MaintainPlanContent planContent){
		return R.status(planContentService.planCommit(planContent));
	}

	/**
	 * 任务维保签字接口
	 * @param signture
	 * @return
	 */
	@ApiLog("保养-维保签字")
	@PostMapping("/signture")
	public R<Boolean> signture(@RequestBody MaintainSignture signture){
		signtureService.signature(signture);
		MaintainPlanContent planContent = planContentService.getById(signture.getPlanId());
		if(planContent.getStatus().equals(TaskStatusEnum.BY_MAINTAIN_SIGN.getStatus())){
			List<Long> elevatorIds = new ArrayList<>();
			elevatorIds.add(planContent.getElevatorId());
			planContentService.updateElevatorStrategy(elevatorIds, true);
		}
		return R.status(Boolean.TRUE);
	}

	/**
	 * 任务客户签字接口
	 * @param signture
	 * @return
	 */
	@ApiLog("保养-客户签字")
	@PostMapping("/signture/estate")
	public R<Boolean> signtureEstate(@RequestBody MaintainSignture signture){
		return R.data(signtureService.signatureEstate(signture));
	}

	/**
	 * 任务客户是否可以签字接口
	 * @param planId
	 * @return
	 */
	@GetMapping("/signture/estate/status")
	public R<HashMap<String,Object>> signtureEstateStatus(Long planId){
		return R.data(signtureService.signatureEstateStatus(planId));
	}

	/**
	 * 获取任务签字
	 * @param planId
	 * @return
	 */
	@TenantIgnore
	@GetMapping("/list/signature")
	public R<List<MaintainSignture>> listSignature(Long planId){
		List<MaintainSignture> signtureList = signtureService.list(Wrappers.<MaintainSignture>lambdaQuery().eq(MaintainSignture::getPlanId,planId));
		if(ObjectUtil.isNotEmpty(signtureList)){
			signtureList.forEach(e -> {
				if(ObjectUtil.isNotEmpty(e.getUserId())){
					String userName = userService.getById(e.getUserId()).getRealName();
					e.setUserName(userName);
				}
			});
		}
		return R.data(signtureList);
	}

//	/**
//	 * 详情
//	 */
//	@GetMapping("/detail")
//	@ApiOperationSupport(order = 1)
//	@ApiOperation(value = "详情", notes = "传入maintainPlanContent")
//	public R<MaintainPlanContentVO> detail(MaintainPlanContent maintainPlanContent) {
//		MaintainPlanContent detail = planContentService.getOne(Condition.getQueryWrapper(maintainPlanContent));
//		return R.data(MaintainPlanContentWrapper.build().entityVO(detail));
//	}


	/**
	 * 首页-我的任务
	 */
	@ApiLog("首页任务列表")
	@PostMapping("/list")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "获取首页数据1.0", notes = "planContentSearchDTO")
	public R<MaintainPlanContentHomeListVo> list(@RequestBody PlanContentSearchDTO planContentSearchDTO) {
		return R.data(planContentService.selectMaintainPlanContentPage(planContentSearchDTO));
	}

	/**
	 * 首页-我的任务
	 */
	@PostMapping("/plan/order/home/page")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "获取首页数据2.0")
	public R<IPage<PlanOrderHomePageVO>> planOrderHomePage(@Valid @RequestBody PlanOrderHomePageSearchDTO searchDTO, @RequestBody Query query) {
		return R.data(planContentService.planOrderHomePage(searchDTO, Condition.getPage(query)));
	}

	/**
	 * 首页-我的任务
	 */
	@PostMapping("/plan/order/home/page/v3")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "获取首页数据3.0")
	public R<IPage<PlanHomeDataVO>> planOrderHomePageV3(@Valid @RequestBody PlanOrderHomePageSearchDTO searchDTO, @RequestBody Query query) {
		return R.data(planContentService.planOrderHomePageV3(searchDTO, Condition.getPage(query)));
	}

	/**
	 * 首页-我的任务-角标统计
	 */
	@PostMapping("/plan/order/home/type/statistics")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "获取首页数据4.0-角标统计")
	public R<List<MaintainPlanContentTypeCountVo>> typeStatistics(@RequestBody PlanOrderHomePage4SearchDTO planContentSearchDTO) {
		return R.data(planContentService.planOrderHomeTypeStatistics(planContentSearchDTO));
	}

	/**
	 * 首页-我的任务4.0
	 */
	@PostMapping("/plan/order/home/page/v4")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "获取首页数据4.0")
	public R<IPage<PlanHomeV4DataVO>> planOrderHomePageV4(@Valid @RequestBody PlanOrderHomePage4SearchDTO searchDTO, @RequestBody Query query) {
		// 2025-09 修改今日也获取历史数据修改为历史数据单独获取
		if(searchDTO.getSearchHistory()){
			searchDTO.setEndTime(String.valueOf(DateUtil.endOfDay(DateUtil.yesterday())));
			searchDTO.setBeginTime(String.valueOf(DateUtil.beginOfDay(DateUtil.offsetDay(DateUtil.date(),-730))));
		}
		return R.data(planContentService.planOrderHomePageV4(searchDTO, Condition.getPage(query)));
	}

	/**
	 * 首页-我的任务4.0-已完成任务列表
	 */
	@PostMapping("/plan/order/home/finish/list/v4")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "首页-我的任务4.0-已完成任务列表")
	public R<List<PlanFinishOrderHomePageV4VO>> planOrderHomeFinishPageV4(@Valid @RequestBody PlanOrderHomePage4SearchDTO searchDTO) {
		return R.data(planContentService.planOrderHomeFinishPageV4(searchDTO));
	}

	/**
	 * 修改 维保任务表
	 */
	@PostMapping("/update")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "修改", notes = "传入maintainPlanContent")
	public R update(@Valid @RequestBody MaintainPlanContent maintainPlanContent) {
		return R.status(planContentService.update(maintainPlanContent));
	}


	@GetMapping("getLocationType")
	public R<List<String>> getLocationTypeOfplanId(Long planId){
		return R.data(planContentService.getLocationTypeOfplanId(planId));
	}

	/**
	 * 新增报障
	 */
	@PostMapping("/malfunctionWorkSave")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "新增报障", notes = "传入repairWorkVO")
	public R<HashMap<String,Object>> malfunctionWorkSave(@Valid @RequestBody RepairWorkVO repairWorkVO) {
		HashMap<String,Object> b = malfunctionWorkService.malfunctionWorkSave(repairWorkVO);
		return R.data(b);
	}

	/**
	 * 修改报障
	 */
	@PostMapping("/malfunctionWorkUpdate/message")
	@ApiOperationSupport(order = 41)
	@ApiOperation(value = "修改报障", notes = "传入repairWorkVO")
	public R<Boolean> malfunctionWorkUpdate(@Valid @RequestBody RepairWorkVO repairWorkVO){
		boolean b = malfunctionWorkService.malfunctionWorkUpdateMessage(repairWorkVO);
		return R.data(b);
	}

	/**
	 * @Author lsay
	 * @Description {
	 *   获取工单及时性类型
	 * }
	 * @Date 16:15 2022/10/27
	 * @return 数据集合
	 **/
	@GetMapping("/timeliness")
	public R<List<Map<String,Object>>> getPlanTimeliness(){
		List<Map<String,Object>> resultMap = Arrays.stream(PlanTimelinessEnum.values()).map(e -> {
			Map<String, Object> map = new HashMap<>(2);
			map.put("value",e.getStatus());
			map.put("name",e.getName());
			return map;
		}).collect(Collectors.toList());
		return R.data(resultMap);
	}

	/**
	 * @Author lsay
	 * @Description {
	 *   获取工单时长类型
	 * }
	 * @Date 16:15 2022/10/27
	 * @return 数据集合
	 **/
	@GetMapping("/duration")
	public R<List<Map<String,Object>>> getPlanDuration(){
		List<Map<String,Object>> resultMap = Arrays.stream(PlanDurationEnum.values()).map(e -> {
			Map<String, Object> map = new HashMap<>(2);
			map.put("value",e.getStatus());
			map.put("name",e.getName());
			return map;
		}).collect(Collectors.toList());
		return R.data(resultMap);
	}

	/**
	 * @Author lsay
	 * @Description {
	 *   获取签到类型
	 * }
	 * @Date 16:15 2022/10/27
	 * @return 数据集合
	 **/
	@GetMapping("/sign/type")
	public R<List<Map<String,Object>>> getPlanSignType(){
		List<Map<String,Object>> resultMap = Arrays.stream(SignErrorTypeEnum.values()).map(e -> {
			Map<String, Object> map = new HashMap<>(2);
			map.put("value",e.getId());
			map.put("name",e.getName());
			return map;
		}).collect(Collectors.toList());
		return R.data(resultMap);
	}

	/**
	 * @Author lsay
	 * @Description {
	 *   获取任务模板使用梯型
	 * }
	 * @Date 10:55 2022/10/28
	 **/
	@GetMapping("/template/elevator/type")
	public R<List<Dict>> getPlanTemplateElevatorType(){
		return R.data(DictCache.getList("apply_elevator_type"));
	}

	/**
	 * @Author lsay
	 * @Description {
	 *   获取任务模板
	 * }
	 * @Date 10:57 2022/10/28
	 * @Param 使用梯型code
	 * @return 模板数据集合
	 **/
	@TenantIgnore
	@GetMapping("/template")
	public R<List<TemplateVO>> getPlanTemplate(String code){
		return R.data(templateService.listByElevatorUseType(code, AuthUtil.getTenantId()));
	}

	/**
	 * 获取模板所有的场景和模板
	 * 树形个够
	 * @param code 编码
	 * @return 数据值
	 */
	@GetMapping("/template/v2")
	@ApiOperation("获取模板场景及模板")
	public R<List<TemplateVO>> getPlanTemplateV2(String code){
		return R.data(templateService.listByElevatorUseTypeV2(code, AuthUtil.getTenantId()));
	}

	/**
	 * 获取首页各种类型工单进行的数据统计
	 * @return 数据集
	 */
	@GetMapping("/planTypeStatistic")
	@ApiOperation(value = "获取首页进行中工单")
	public R<List<PlanTypeStatisticVo>> getPlanTypeStatistic(){
		return R.data(planContentService.getPlanTypeStatistic());
	}

	/**
	 * 获取同类型工单是否存在未签退
	 * @param planId
	 * @return
	 */
	@GetMapping("/allow/sign")
	public R<Map<String,Object>> getPlanAllowSign(Long planId){
		return R.data(planContentService.getPlanAllowSign(planId));
	}

	/**
	 * @Author lsay
	 * @Description {
	 *   更新工单详情
	 * }
	 * @Date 8:58 2023/4/25
	 * @Param
	 * @return
	 **/
	@PostMapping("/detail/update")
	public R<Boolean> planDetailUpdate(@RequestBody MaintainPlanContent planContent){
		return R.data(planContentService.planDetailUpdate(planContent));
	}

	/**
	 * @Author lsay
	 * @Description {
	 *   更新电梯运行状态时向订阅该电梯物业用户发送模板消息
	 * }
	 * @Date 10:50 2023/5/24
	 * @Param
	 * @return
	 **/
	@GetMapping("/bot/send/msg")
	public R<Boolean> botSendMsg(Long planId,Integer isStop){
		return R.data(planContentService.botSendMsg(planId,isStop));
	}

	@PostMapping("/maintain/plan/calendar/data")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "保养计划日历图")
	public R maintainPlanCalendarData(@RequestBody @Valid MaintainPlanCalendarDataDTO calendarDataDTO) {
		return R.data(planContentService.maintainPlanCalendarData(calendarDataDTO));
	}

	@PostMapping("/getDatePlanInfoList/down/excel")
	@ApiOperationSupport(order = 8)
	@ApiOperation("获取日历工单数据下载")
	public R<String> getDatePlanInfoListDownExcel(@RequestBody @Valid MaintainPlanCalendarDataDownDTO calendarDataDTO) throws IOException {
		return R.data(planContentService.getDatePlanInfoListDownExcel(calendarDataDTO));
	}

	@PostMapping("/getDatePlanInfoList/down/statistics")
	@ApiOperationSupport(order = 9)
	@ApiOperation("获取日历工单下载统计数")
	public R getDatePlanInfoListDownStatistics(@RequestBody @Valid MaintainPlanCalendarDataDownDTO calendarDataDTO){
		return R.data(planContentService.getDatePlanInfoListDownStatistics(calendarDataDTO));
	}

	@PostMapping("/plan/calendar/list/statistics")
	@ApiOperationSupport(order = 10)
	@ApiOperation(value = "保养计划日历列表明细统计")
	public R getPlanCalendarListStatistics(@RequestBody @Valid MaintainPlanCalendarDataDTO calendarDataDTO) {
		return R.data(planContentService.getPlanCalendarListStatistics(calendarDataDTO));
	}

	@GetMapping("/user/overdue/count")
	public R<Map<String,Long>> selectPlanUserOverdueCount(){
		return R.data(planContentService.selectPlanUserOverdueCount());
	}

	/**
	 * @Author lsay
	 * @Description {
	 *   保养工单离线同步数据
	 * }
	 * @Date 11:14 2024/7/8
	 * @Param
	 * @return
	 **/
//	@ApiLog("保养-离线工单数据同步")
	@TenantIgnore
	@PostMapping("/by/offline/update")
	public R<Boolean> byOfflineUpdate(@RequestBody ByPlanOfflineDetailDTO dto){
		return R.data(planContentService.byOfflineUpdate(dto));
	}

	/**
	 * @Author lsay
	 * @Description {
	 *   保养工单离线数据冗余
	 * }
	 * @Date 11:15 2024/7/8
	 * @Param
	 * @return
	 **/
//	@ApiLog("保养-离线工单数据冗余")
	@TenantIgnore
	@PostMapping("/by/offline/data/save")
	public R<Boolean> byOfflineDataSave(@RequestBody ByPlanOfflineDetailDTO dto){
		MaintainPlanContentOffline offline = new MaintainPlanContentOffline();
		offline.setPlanId(dto.getPlanId());
		offline.setUserId(AuthUtil.getUserId());
		offline.setTenantId(AuthUtil.getTenantId());
		offline.setOfflineData(JSONObject.parseObject(JSONObject.toJSONString(dto)));
		return R.data(planContentOfflineService.save(offline));
	}

	@TenantIgnore
	@GetMapping("/old/offline/by/plan/list")
	@ApiOperationSupport(order = 11)
	@ApiOperation(value = "离线保养缓存数据1.0")
	public R<List<PlanContentElevatorVo>> getOldOfflineByPlanList() {
		return R.data(planContentService.getOldOfflineByPlanList());
	}

	@TenantIgnore
	@GetMapping("/offline/by/plan/list")
	@ApiOperationSupport(order = 11)
	@ApiOperation(value = "离线保养缓存数据2.0")
	public R<List<OfflineByPlanListVO>> getOfflineByPlanList() {
		return R.data(planContentService.getOfflineByPlanList());
	}
}
